#include "DBConnectionLst.h"
#include "common.h"

CDBConnectionLst::CDBConnectionLst()
	:m_nCount(0)
{

}


CDBConnectionLst::~CDBConnectionLst()
{
	m_nCount = 0;
	m_mapConn.clear();
}

void CDBConnectionLst::AddFreeConn(DBConnectionPtr pConn)
{
	std::lock_guard<std::mutex> _lock(m_mutex);
	DBCONNINFO* pCnnInfo = GetKeyResult(m_mapConn, m_nCount, true);
	if (pCnnInfo)
	{
		pCnnInfo->nConnID = m_nCount;
		pCnnInfo->nIsUsed = 0;
		pCnnInfo->pDBConn = pConn;
		pCnnInfo->nTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());;
		m_nCount++;
	}
}

DBCONNINFO* CDBConnectionLst::AddBusyConn(DBConnectionPtr pConn)
{
	std::lock_guard<std::mutex> _lock(m_mutex);
	return AddBusyConn_nolock(pConn);
}


DBCONNINFO* CDBConnectionLst::AddBusyConn_nolock(DBConnectionPtr pConn)
{
	DBCONNINFO* pCnnInfo = GetKeyResult(m_mapConn, m_nCount, true);
	if (pCnnInfo)
	{
		pCnnInfo->nConnID = m_nCount;
		pCnnInfo->nIsUsed = 1;
		pCnnInfo->pDBConn = pConn;
		pCnnInfo->nTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());;

		m_nCount++;
	}
	return pCnnInfo;
}

DBCONNINFO* CDBConnectionLst::FindFreeDBConn()
{
	std::lock_guard<std::mutex> _lock(m_mutex);
	return FindFreeDBConn_nolock();
}

DBCONNINFO* CDBConnectionLst::FindFreeDBConn_nolock()
{
	DBCONNINFO *pDbInfo = NULL;
	for (auto& it : m_mapConn)
	{
		if (it.second.nIsUsed == 0 &&
			(it.second.pDBConn->IsConnect() || it.second.pDBConn->ReConnect()))
		{
			it.second.nIsUsed = 1;
			it.second.nTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
			pDbInfo = &it.second;
			break;
		}
	}
	return pDbInfo;
}

void CDBConnectionLst::RetDBConn(unsigned int nConnId)
{
	std::lock_guard<std::mutex> _lock(m_mutex);
	DBCONNINFO* pCnnInfo = GetKeyResult(m_mapConn, nConnId, false);
	if (pCnnInfo)
	{
		pCnnInfo->nTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
		pCnnInfo->nIsUsed = 0;
	}
}

void CDBConnectionLst::RemoveDBConn(unsigned int nConnId)
{
	std::lock_guard<std::mutex> _lock(m_mutex);
	m_mapConn.erase(nConnId);
}

void CDBConnectionLst::Clear()
{
	m_nCount = 0;
	m_mapConn.clear();
}

unsigned int CDBConnectionLst::GetDBCount()
{
	return m_mapConn.size();
}

void CDBConnectionLst::CheckExpire(int64_t nExpired)
{
	std::lock_guard<std::mutex> _lock(m_mutex);
	auto it = m_mapConn.begin();
	while (it != m_mapConn.end())
	{
		if (it->second.nTime <= nExpired)
		{
			m_mapConn.erase(it++);
		}
		else
			++it;
	}
}

unsigned int CDBConnectionLst::GetFreeCount()
{
	int nCount = 0;
	std::lock_guard<std::mutex> _lock(m_mutex);
	for (auto it : m_mapConn)
	{
		if (it.second.nIsUsed == 0)
		{
			nCount++;
		}
	}
	return nCount;
}

